/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package workers;

import entities.Categories;
import entities.Merchantassociatedcategories;
import entities.Merchants;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.PostConstruct;
import javax.ejb.DependsOn;
import javax.ejb.EJB;
import javax.ejb.Local;
import javax.ejb.LocalBean;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.apache.log4j.Logger;
import session.CategoriesFacade;
import session.MerchantassociatedcategoriesFacade;
import session.MerchantsFacade;

/**
 *
 * @author bsmith
 */
//@Startup
//@DependsOn("MerchantsFacade")
@Singleton(name = "MerchantsWorker")
@Local
public class MerchantsWorkerImpl implements MerchantsWorker {

    Logger logger = Logger.getLogger(MerchantsWorkerImpl.class);
    @EJB
    private MerchantsFacade ejbMerchantsFacade;
    @EJB
    private MerchantassociatedcategoriesFacade ejbMerchantassociatedcategoriesFacade;
    @EJB
    private CategoriesFacade ejbCategoriesFacade;
    private Map<String, Integer> merchantsMatchers = null;

    public MerchantsWorkerImpl() {
    }

    public MerchantsWorkerImpl(MerchantsFacade ejbMerchantsFacade) {
        this.ejbMerchantsFacade = ejbMerchantsFacade;
    }

    @PostConstruct
    public void startup() {
        logger.info("Started Merchants Worker ...");
    }

    /**
     * Matchers are case insensitive
     */
    private void gatherMatchers() {
        merchantsMatchers = new HashMap<String, Integer>();
        EntityManager em = ejbMerchantsFacade.getEntityManager();
        Query q = em.createNamedQuery("Merchants.findAll");
        List<Merchants> merchants = q.getResultList();//findAll();
        for (Merchants m : merchants) {
            em.refresh(m);
            merchantsMatchers.put(m.getMatcher().toLowerCase(), m.getId());
            logger.info("gathered Matcher: " + m.getMatcher());
        }
    }

    public void lookup() {
        logger.debug("merchantsWorker Lookup!");
    }

    public Merchants lookupMerchant(String merchantFromStatement) throws Exception {
        Integer theMerchant = null;
        String merchantFromStatementLC = merchantFromStatement.toLowerCase();
        gatherMatchers();
        logger.debug("  LookupMerchant - from statement:" + merchantFromStatementLC);
        for (String matcher : merchantsMatchers.keySet()) {
            String matcherLC = matcher.toLowerCase();
            logger.debug("  matcher:" + matcherLC);
            Pattern p = Pattern.compile(matcher);
            Matcher m = p.matcher(merchantFromStatementLC);
            if (m.find()) {
                logger.debug("   matched!");
                theMerchant = merchantsMatchers.get(matcher);
                break;
            }
        }
        if (theMerchant != null) {
            EntityManager em = ejbMerchantsFacade.getEntityManager();
            Query merchantsQuery = em.createNamedQuery("Merchants.findById");
            merchantsQuery.setParameter("id", theMerchant);
            List<Merchants> merchants = merchantsQuery.getResultList();
            if (merchants.size() == 0) {
                throw new Exception("A matcher matched but the merchants List for that Id is empty");
            }
            return merchants.get(0);
        } else {
            return null;
        }
    }

    public Merchants getNoMerchantMatchMerchant() {
        // todo implmenent
        return null;
    }

    public List<Categories> lookupCategoriesForMerchant(Merchants merchant) {
        EntityManager em = ejbMerchantassociatedcategoriesFacade.getEntityManager();
        em.flush();
        Query merchants2CatsQuery = em.createNamedQuery("Merchantassociatedcategories.findByCatsForMerchantId");
        merchants2CatsQuery.setParameter("merchantid", merchant);
        List<Merchantassociatedcategories> merchantassociatedcategoriesList = merchants2CatsQuery.getResultList();
        List<Categories> categoriesList = new ArrayList<Categories>();
        for (Merchantassociatedcategories mac : merchantassociatedcategoriesList) {
            categoriesList.add(mac.getCategoryid());
        }
        return categoriesList;
    }

    public Categories getNoCategoryCategory() {
        // todo implmenent
        return null;
    }
    
    private MerchantsFacade getFacade() {
        return ejbMerchantsFacade;
    }

//    public List<Categories> returnCategories(List<Merchantassociatedcategories> merchantassociatedcategoriesList) {
//        List<Categories> categoriesList = new ArrayList<Categories>();
//        EntityManager em = ejbCategoriesFacade.getEntityManager();
//        em.flush();
//
//        for (Merchantassociatedcategories mac : merchantassociatedcategoriesList) {
//
//            Query catQuery = em.createNamedQuery("Categories.findById");
//            catQuery.setParameter("id", mac.getCategoryid());
//            List<Categories> cats = catQuery.getResultList();
//            categoriesList.add(cats.get(0));
//        }
//
//        return categoriesList;
//    }

    @Override
public Merchants createNewMerchant(String merchant) {
        if (merchant == null || merchant.length() == 0) {
            return null;
        }
        String fixedMerchant = Merchants.replaceProblemChars(merchant);
        System.out.println(new StringBuilder().append("createNewMerchant for:").append(fixedMerchant).toString());
        getFacade().create(new Merchants(fixedMerchant));
        int id;
        Query q = getFacade().getEntityManager().createNamedQuery("Merchants.findByMerchant");
        q.setParameter("merchant", fixedMerchant);
        Merchants m = (Merchants) q.getSingleResult();
        
        return m;
    }
}
